﻿#include "PLCClientManage.h"
#include "ModbusTcpClient.h"
#include "FinsUdp.h"
#include "FinsTcp.h"
#include "FXProtocol.h"
#include <QApplication>
#include <QSettings>

#pragma execution_character_set("utf-8")

PLCClientManage::PLCClientManage(QObject *parent)
    : QObject{parent}
{
    //setConfigWriteOneFunc(void (*func)(const PLCClientConfig& config));
    //setConfigReadAllFunc(QMap<QString, PLCClientConfig> (*func)());
    //setConfigReadOneFunc(PLCClientConfig (*func)(QString camName));
    //initWgtPLCClientStatus();
    //initPLCClientManageWidget();
    //initPLCClientAll();
    //startWorker();

#if QT_VERSION >= 0x060000
// Qt 6 的代码
#else
    // Qt 5 的代码
    qRegisterMetaTypeStreamOperators<PLCClientConfig>("PLCClientConfig");
#endif

    configWriteOne = [](const PLCClientConfig& config){
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.setValue("PLCClientConfig/" + config.name, QVariant::fromValue(config));
    };
    configReadOne = [](QString name)->PLCClientConfig{
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        PLCClientConfig config = iniFile.value("PLCClientConfig/" + name).value<PLCClientConfig>();
        return config;
    };
    configReadAll = []()->QMap<QString, PLCClientConfig>{
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.beginGroup("PLCClientConfig");
        QStringList keyList = iniFile.childKeys();
        QMap<QString, PLCClientConfig> mapConfig;
        for(auto key : keyList){
            PLCClientConfig config = iniFile.value(key).value<PLCClientConfig>();
            mapConfig.insert(config.name, config);
        }
        iniFile.endGroup();
        return mapConfig;
    };
}
void PLCClientManage::setConfigWriteOneFunc(void (*func)(const PLCClientConfig& config))
{
    configWriteOne = func;
}
void PLCClientManage::setConfigReadAllFunc(QMap<QString, PLCClientConfig> (*func)())
{
    configReadAll = func;
}
void PLCClientManage::setConfigReadOneFunc(PLCClientConfig (*func)(QString camName))
{
    configReadOne = func;
}
void PLCClientManage::startWorker()
{
    for(auto thread : mMapComThread.values()){
        thread->start();
    }
}
void PLCClientManage::checkPLCClientStatus()
{
    bool isStart = true;
    if(mMapComStart.size() != mMapPLCClient.size()){
        isStart = false;
        goto checkEnd;
    }
    for(auto status : mMapComStart.values()){
        if(!status){
            isStart = false;
            break;
        }
    }
checkEnd:
    emit sigPLCClientStatus(isStart);
}
void PLCClientManage::initPLCClientAll()
{
    QMap<QString, PLCClientConfig> mapComConfig = configReadAll();
    for(auto key : mapComConfig.keys()){
        initPLCClientOne(mapComConfig.value(key));
    }
}
void PLCClientManage::initPLCClientOne(PLCClientConfig config)
{
    PLCClientBase* comWorker;
    switch (config.type) {
    case PCT_ModbusTcp:
        comWorker = new ModbusTcpClient(config.name);
        break;
    case PCT_FinsTcp:
        comWorker = new FinsTcp(config.name);
        break;
    case PCT_FinsUdp:
        comWorker = new FinsUdp(config.name);
        break;
    case PCT_FX:
        comWorker = new FXProtocol(config.name);
        break;
    default:
        comWorker = new ModbusTcpClient(config.name);
        break;
    }
    comWorker->setConfig(config);
    mMapPLCClient.insert(config.name, comWorker);

    QThread* comThread = new QThread();
    mMapComThread.insert(config.name, comThread);

    comWorker->moveToThread(comThread);
    connect(comThread, &QThread::started, comWorker, &PLCClientBase::onInit);
    connect(qApp, &QApplication::aboutToQuit, comWorker, &PLCClientBase::onQuit);
    connect(comWorker, &QObject::destroyed, comThread, &QThread::quit);
    connect(comThread, &QThread::finished, comThread, &QThread::deleteLater);

    wgtPLCClientStatus->addOne(config.name);

    //在相机管理页面添加一个
    mPLCClientManageWidget->addPLCClient(mMapPLCClient.value(config.name));

    //连接相机的状态信号，并显示
    QString comName = config.name;
    connect(comWorker, &PLCClientBase::sigStateChanged, this, [&, comName](const ComState& status){
        wgtPLCClientStatus->setStatus(comName, PLCClientBase::mapPLCStateText.value(status));
    });

}
void PLCClientManage::initWgtPLCClientStatus()
{
    wgtPLCClientStatus = new PLCClientStatusWidget();
    wgtPLCClientStatus->setMinimumWidth(200);
}
void PLCClientManage::initPLCClientManageWidget()
{
    mPLCClientManageWidget = new WidgetPLCClient("相机调试");
    connect(mPLCClientManageWidget, &WidgetPLCClient::sigAddOne, this, &PLCClientManage::onAddOne);
    connect(mPLCClientManageWidget, &WidgetPLCClient::sigConfigChanged, this, &PLCClientManage::onConfigChanged);
    connect(mPLCClientManageWidget, &WidgetPLCClient::sigDeleteOne, this, &PLCClientManage::onDeleteOne);
}
void PLCClientManage::onAddOne(const PLCClientConfig& config)
{
    if(mMapPLCClient.contains(config.name))
        return;
    configWriteOne(config);
    initPLCClientOne(config);
    mMapComThread.value(config.name)->start();
}
void PLCClientManage::onDeleteOne(const QString& name)
{
    if(!mMapPLCClient.contains(name))
        return;
    PLCClientBase* com = mMapPLCClient.take(name);
    com->deleteLater();
    com = nullptr;
    wgtPLCClientStatus->removeOne(name);
}
void PLCClientManage::onConfigChanged(const PLCClientConfig& config)
{
    configWriteOne(config);
}

